package com.gitee.liuzhi.microservice.minio.server.config;

import com.gitee.liuzhi.microservice.minio.server.properties.MinioProperties;
import com.gitee.liuzhi.microservice.minio.server.utils.MinioUtil;
import io.minio.MinioClient;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.*;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Arrays;

/**
 * Created by 2022/4/24/0024
 *
 * @author LiuZhi
 * @version V1.0
 * @description: MinioClient 自动配置类
 */
@Slf4j
@Configuration
@ConditionalOnClass(name = "io.minio.MinioClient")
@EnableConfigurationProperties(value = MinioProperties.class)
public class MinioConfiguration {

    @Bean
    public MinioClient minioClient(MinioProperties minioProperties) {
        try {
            MinioClient minioClient = MinioClient.builder()
                    .endpoint(minioProperties.getUrl())
                    .httpClient(getUnsafeOkHttpClient())
                    .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                    .build();
            MinioUtil.setMinioClient(minioClient);
            if (StringUtils.isBlank(minioProperties.getPublicUrl())) {
                minioProperties.setPublicUrl(minioProperties.getUrl());
            }
            MinioUtil.setMinioProperties(minioProperties);
            MinioUtil.setBucketName(minioProperties.getBucketName());
            return minioClient;
        } catch (Exception e) {
            log.error(String.format("minio init fail. message:%s", e.getMessage()), e);
            throw new RuntimeException();
        }
    }

    private static OkHttpClient getUnsafeOkHttpClient() {
        try {
            TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {

                        }

                        @Override
                        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {

                        }

                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[]{};
                        }
                    }
            };
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new SecureRandom());
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory, getX509TrustManager());
            builder.hostnameVerifier((s, sslSession) -> true);
            return builder.build();
        } catch (Exception e) {
            log.error(String.format("create OkHttpClient fail. message:%s", e.getMessage()), e);
            throw new RuntimeException();
        }
    }

    private static X509TrustManager getX509TrustManager() {
        try {
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init((KeyStore) null);
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
            if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
                throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
            }
            return (X509TrustManager) trustManagers[0];
        } catch (Exception e) {
            log.error(String.format("create OkHttpClient fail. message:%s", e.getMessage()), e);
            throw new RuntimeException();
        }
    }

}
